package cn.edu.qfnu.oj.entity;

import com.google.common.base.Objects;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Entity
@DynamicUpdate
@DynamicInsert
public class Student implements Serializable {

    private static final long serialVersionUID = -2050079980087648855L;
    private String studentId; // 学号
    private String password;  //密码
    private String sex;  //性别
    private String nickname; //昵称
    private String realName; // 真实姓名
    private String school; // 学校
    private String email; //邮箱
    private Level level; // 双排位
    private String sign; // 个性签名
    private Integer submitCount; //提交总计
    private Integer ACCount; // AC总计
    private Set<Attend> attends = new HashSet<>(); // 提交记录
    private Set<Contest> contests = new HashSet<>();  //参加的比赛集合
    private Classes classFrom; // 班级
    private List<Submit> submits = new ArrayList<>(); // 提交记录

    public Student() {}

    public Student(String studentId, String password, String sex,
                   String nickname, String realName, String school, String email) {
        this.studentId = studentId;
        this.password = password;
        this.sex = sex;
        this.nickname = nickname;
        this.realName = realName;
        this.school = school;
        this.email = email;
        this.sign = " ";
        this.ACCount = 0;
        this.submitCount = 0;
    }

    public Student(String studentId, String password, String email) {
        this.studentId = studentId;
        this.password = password;
        this.email = email;
        this.ACCount = 0;
        this.nickname = "";
        this.realName = "";
        this.school = "";
        this.sex = "";
        this.sign = "";
        this.submitCount = 0;
    }

    public Student(String studentId, String email) {
        this.studentId = studentId;
        this.email = email;
    }

    @Id
    @Column(name = "student_id", length = 12, unique = true)
    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    @Column(name = "password", length = 16)
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Column(name = "sex", length = 8)
    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Column(name = "nickname", length = 16)
    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    @Column(name = "real_name", length = 16)
    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    @Column(length = 16)
    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    @Column(length = 32, unique = true)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Column(length = 64)
    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    @Column(name = "submit_count")
    public Integer getSubmitCount() {
        return submitCount;
    }

    public void setSubmitCount(Integer submitCount) {
        this.submitCount = submitCount;
    }

    @Column(name = "AC_count")
    public Integer getACCount() {
        return ACCount;
    }

    public void setACCount(Integer acCount) {
        this.ACCount = acCount;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equal(studentId, student.studentId) &&
                Objects.equal(password, student.password) &&
                Objects.equal(sex, student.sex) &&
                Objects.equal(nickname, student.nickname) &&
                Objects.equal(realName, student.realName) &&
                Objects.equal(school, student.school) &&
                Objects.equal(email, student.email) &&
                Objects.equal(level, student.level) &&
                Objects.equal(sign, student.sign) &&
                Objects.equal(submitCount, student.submitCount) &&
                Objects.equal(ACCount, student.ACCount) &&
                Objects.equal(attends, student.attends) &&
                Objects.equal(contests, student.contests) &&
                Objects.equal(classFrom, student.classFrom) &&
                Objects.equal(submits, student.submits);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(studentId, password, sex, nickname, realName,
                school, email, level, sign, submitCount, ACCount,
                attends, contests, classFrom, submits);
    }

    //一个学生可以有多个参与记录，但这多个参与记录只能隶属于一个学生
    //因此学生与参与记录之间是一对多关系
    @OneToMany(mappedBy = "student")  // 学生的参与记录一对多关系交给提交记录维护
    public Set<Attend> getAttends() {
        return attends;
    }

    public void setAttends(Set<Attend> attends) {
        this.attends = attends;
    }


    //一个学生可以参加多个比赛，但这多个比赛可以被不同的学生参加
    //因此学生与比赛是多对多关系
    @ManyToMany  //维护学生与比赛之间的多对多关系
    @JoinTable(name = "contest_student",
            joinColumns = @JoinColumn(name = "student_id", referencedColumnName = "student_id"),
            inverseJoinColumns = @JoinColumn(name = "contest_id", referencedColumnName = "id"))
    public Set<Contest> getContests() {
        return contests;
    }

    public void setContests(Set<Contest> contestByStudentId) {
        this.contests = contestByStudentId;
    }

    //一个学生只能在一个班级里，而一个班级可以由多个学生
    //因此学生与班级是多对一关系
    @ManyToOne // 维护学生与班级的多对一关系
    @JoinColumn(name = "class_id", referencedColumnName = "id")
    public Classes getClassFrom() {
        return classFrom;
    }

    public void setClassFrom(Classes classes) {
        this.classFrom = classes;
    }

    //一个学生可以有多个提交记录，而这多个提交记录只能隶属于一个学生
    //因此学生与提交记录是多对一关系
    @OneToMany(mappedBy = "student") // 学生与提交记录的一对多关系交给提交记录维护
    public List<Submit> getSubmits() {
        return submits;
    }

    public void setSubmits(List<Submit> submits) {
        this.submits = submits;
    }

    //一个学生只有一个段位信息，一个段位信息隶属于一个学生
    @OneToOne(mappedBy = "student") // 学生与段位的一对一关系交给段位维护
    public Level getLevel() {
        return level;
    }

    public void setLevel(Level level) {
        this.level = level;
    }
}
